﻿using Newtonsoft.Json;
using System.Collections.Concurrent;
using System.Reflection;
using wRPC;
using wRPCclient;
using wRPCService;

namespace gateway
{
    public class CallServer
    {
        public
        static ConcurrentDictionary<string, ClientChannelQueue> _serviceDic = new ConcurrentDictionary<string, ClientChannelQueue>();
        public static Dictionary<string, object> keyValuePairs = new Dictionary<string, object>();
        public static void heartbeat()
        {

            //  System.Threading.ThreadPool.QueueUserWorkItem(new WaitCallback(keep),null);
        }
        public static bool distributed = false;



        public static object CallService(server ser, String rt, String rls, object[] objs,
            Dictionary<string, String> Headers, Dictionary<string, String> keysCookies, ClientChannel.recdata rec = null, ClientChannel.recdataStream recStream = null,
            wRPCclient.filedata fd = null, Stream Body = null)
        {
            bool locked = false;
            wRPCclient.ClientChannel clientChannel = null;

            ClientChannelQueue CCQ = null;

            try
            {
                if (distributed)
                {

                    clientChannel = new wRPCclient.ClientChannel(ser.IP, ser.Port,10);
                    CCQ = new ClientChannelQueue();
                    CCQ.clientChannel = clientChannel;
                    clientChannel.Headers = Headers;
                    clientChannel.Cookies = keysCookies;
                    
                    if (fd != null)
                    {
                        clientChannel.Filedata = fd;

                    }
                    clientChannel.recs = rec;
                    clientChannel.recsStream = recStream;
                    var data = clientChannel.Call<object>(rt, rls, objs);

                    return Newtonsoft.Json.JsonConvert.SerializeObject(data);

                }
                else
                {


                    //单机运行
                    if (!keyValuePairs.ContainsKey(rt))
                    {

                        return JsonConvert.SerializeObject(new { code = 503, msg = "server Route error" });

                    }
                    object obj = keyValuePairs[rt];
                    Type t = obj.GetType();
                    obj = t.Assembly.CreateInstance(t.FullName);
                    MethodInfo mi = t.GetMethod(rls);
                    if (mi != null)
                    {
                        InstallFunAttribute myattribute = (InstallFunAttribute)Attribute.GetCustomAttribute(mi, typeof(InstallFunAttribute));
                        if (myattribute != null)
                        {

                            if (obj is FunctionBase)
                            {
                                (obj as FunctionBase).P2Server = null;
                                (obj as FunctionBase).soc = null;
                            }
                            if (obj is FunctionBase && Headers != null)
                            {


                                (obj as FunctionBase).Headers = Headers;


                            }
                            if (obj is FunctionBase && Body != null)
                            {
                                (obj as FunctionBase).Body = Body;




                                if (obj is FunctionBase && keysCookies != null)
                                {



                                    (obj as FunctionBase).Cookies = keysCookies;
                                    
                                    AuthorizeAttribute Authorizeattribute = (AuthorizeAttribute)Attribute.GetCustomAttribute(mi, typeof(AuthorizeAttribute));
                                    if (Authorizeattribute != null)
                                    {
                                        if (Authorizeattribute.Project != "")
                                            if (Authorizeattribute.Project != keysCookies["project"])
                                            {
                                                String tmpdata = Newtonsoft.Json.JsonConvert.SerializeObject(new { code = "401", message = "权限不足！" });
                                                 
                                                return tmpdata;
                                            }
                                        if (Authorizeattribute.Role != "")
                                            if (Authorizeattribute.Role != keysCookies["Role"])
                                            {
                                                String tmpdata = Newtonsoft.Json.JsonConvert.SerializeObject(new { code = "401", message = "权限不足！" });
                                               // P2Server.Send(soc, 0x01, GZIP.GZipCompress(tmpdata));
                                                return tmpdata;
                                            }
                                    }

                                }
                                if (obj is FunctionBase && fd != null)
                                {
                                    wRPC.filedata ffd = new wRPC.filedata();
                                    ffd.data = fd.data;
                                    ffd.filename = fd.filename;
                                    ffd.filetype = fd.filetype;
                                    (obj as FunctionBase).Filedata = ffd;

                                }
                                ParameterInfo[] paramsInfo = mi.GetParameters();//得到指定方法的参数列表 
                                if (paramsInfo.Length != objs.Length)
                                {
                                    return JsonConvert.SerializeObject(new { code = 503, msg = "参数不正确" });
                                }
                                for (int i = 0; i < objs.Length; i++)
                                {

                                    Type tType = paramsInfo[i].ParameterType;

                                    //如果它是值类型,或者String   

                                    if (tType.Equals(typeof(string)) || (!tType.IsInterface && !tType.IsClass))

                                    {

                                        //改变参数类型   
                                        //HttpUtility.UrlDecode
                                        objs[i] = (Convert.ChangeType(objs[i], tType));

                                    }
                                    else if (tType.Equals(typeof(byte)) || tType.Equals(typeof(byte[])) || (!tType.IsInterface && !tType.IsClass))
                                    {
                                        objs[i] = Convert.FromBase64String(objs[i].ToString());
                                    }
                                    else if (tType.IsClass)//如果是类,将它的json字符串转换成对象   

                                    {

                                        objs[i] = Newtonsoft.Json.JsonConvert.DeserializeObject(objs[i].ToString(), tType);

                                    }

                                }

                                //调用API方法，同步或异步的处理放到了AOP内部
                                object rpcdata = Aop.Invoke(mi, obj, objs);
                                if (rpcdata is byte[])
                                    return rpcdata;
                                return rpcdata is null ? string.Empty : JsonConvert.SerializeObject(rpcdata);
                                //DateTime dt2 = DateTime.Now;
                                //Console.WriteLine("service:" + (dt2 - P2Server.dt).TotalMilliseconds);


                            }
                        }
                    }
                }
            }
            catch (Exception e)
            {
                //if (!CCQ.clientChannel.connection())
                //{

                //}
                // _serviceDic.TryRemove(ser.IP + ":" + ser.Port, out CCQ);
                Console.WriteLine(e);
                return JsonConvert.SerializeObject(new { code = 503, msg = "服务器错误" });
            }
            finally
            {
                if (clientChannel != null)
                    clientChannel.Dispose();

            }

            return JsonConvert.SerializeObject(new { code = 503, msg = "服务器错误" });
        }
    }
       
        
        public class ClientChannelQueue
    {
        public ClientChannel clientChannel;
        public SpinLock _spinLock = new SpinLock();
    }
}
